import axios from 'axios'
import store from '@/store'
import router from '@/router'

const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  // axios请求的完整地址：baseURL+url
  // 不能让aixos直接去请求http://开头的外链地址，而是要请求/开头还得名中本地开发服务器里代理规则
  // 知识点5：请求的路径 问题
  // aixos/script标签src/img标签src/link和href，都会发起一次请求
  // 如果是./开头的地址，找当前文件夹
  // 如果是http开头的地址，找到外链外部服务器（链接网路）
  // 如果是/开头的地址，忽略文件夹，直接找到当前运行时，所在服务器（本项目用的是这个，看vue.config.js给的key）
  timeout: 5000
})
// 请求拦截器
// 知识点12：js文件中能否使用this.$store?
// 不能，因为这个this关键字不是Vue组件对象，无法查找原型链上$store
// 但是this.$store为了拿到的是store/index.js导出store对象
// 解决：我们在undefined导入过来使用，是同一个store对象

service.interceptors.request.use(
  config => {
    // console.log(config)//配置项
    // const token = store.state.user.token//原始这样写
    const token = store.getters.token
    if (token) {//如果token有值 就把请求头放进去以及token
      config.headers.Authorization = `Bearer ${token}`//拼接放入 token
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)
// 响应拦截器
// 知识点6：axios内部的处理机制
// 方式1：http状态码处理
// 1.http状态码为2xx, 3xx，就会给Promise对象位置，返回成功的结果（resolve())
// 2.http状态码为4xx, 5xx，就会给Promise对象位置，返回错误的结果（reject())
// 如果想做一些操作，可以在aixos的响应拦截器，自己来回处理返回结果
// 方式2：后台返回的对象里code字段/success字段（’逻辑字段'判断）只是针对于token过期


// 后台返回数据的类型
// 类型1：失败的请求，后台会返回4..的http的状态码（错误）
// ‘http状态码，来标记失败情况

// 类型2：无论成功/失败的请求，后台都会返回http状态200(ok)
// 但是在‘数据的字段“上，区别成功/失败

// 知识点10：axios内部会把后台返回的数据直接放到data字段下面（第一个data是axios处理的）


// 补充：http状态码，由本次请求后，后端进行设置返回的
service.interceptors.response.use(
  response => {//http状态码为2xx, 3xx走这里，所以需要根据字段判定
    // console.log(response)//打印出来的是{data: {…}, status: 200, statusText: 'OK', headers: {…}, config: {…},…}
    const { message, success } = response.data//进行解构赋值
    if (success === false) {//失败
      return Promise.reject(new Error(message))
    } else {//成功
      // 返回response返回的还是axios处理的结果对象（逻辑那边歹.data.data）拿到后台返回值
      // 返回response.data--返回的就是后台返回的响应对象（逻辑那边拿到的真正的数据.data）拿到返回值
      return response.data//特殊:他返回到的是axios调用在原地留下的'promis'对象位置（逻辑页面await后面）
    }

  },
  error => {//http状态码为4xx, 5xx，走这里
    // 身份过期，后台双重返回401，逻辑（codeh和status）状态码（http）
    // 前置非空判断（error有值，才会执行 && 后面的代码）
    // 确保error有值，在.response，.reponse有值，在.status
    // 防止null.xxx语法报错代码终止
    // if(error&&error.response&&error.response.status===401){
    //   身份过期，删除所有cookie，终止vuex，强制回到登录页面
    // }
    // 但是账号密码失败的时候返回的是200，用逻辑判断，最好同意
    // code更好，因为401如果有多个情况，success只能判断失败，我们可以跟后台商量code值不同错误不同
    // 1000成功 10002身份过期 10004 xxx
    console.dir(error)

    // 这里写token失效过期
    if (error.response.data.code === 10002) {//身份过期
      store.commit('user/RESET_STATE')//取出token
      store.commit('user/ DEL_TOKEN')//删除token，内部删除
      // router.currentRouter路由对象内置的，也拿到当前页面路由信息对象
      router.replace(`/login?redirect=${encodeURIComponent(router.currentRoute.fullPath)}`)//调回登录页
      // 效果：手动、等2小时，让本地cookie里token过期，舒心网页会强制回到登录页面
    }
    return Promise.reject(error)// 相当于reject(error)
  }
)

export default service
